package com.hhit.zhgd.service.impl

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
import com.hhit.zhgd.dao.ZhgdMachineryInfoMapper
import com.hhit.zhgd.domain.dto.MachineryInfoByNameDTO
import com.hhit.zhgd.domain.dto.MachineryTableInfoDTO
import com.hhit.zhgd.domain.dto.StatisticMachineryInfoDTO
import com.hhit.zhgd.domain.entity.ZhgdMachineryAlarm
import com.hhit.zhgd.domain.entity.ZhgdMachineryInfo
import com.hhit.zhgd.domain.response.BaseResp
import com.hhit.zhgd.service.ZhgdMachineryAlarmService
import com.hhit.zhgd.service.ZhgdMachineryInfoService
import com.hhit.zhgd.utils.compare
import com.hhit.zhgd.utils.formatDate
import com.hhit.zhgd.utils.formatString
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import java.sql.SQLIntegrityConstraintViolationException
import java.util.*
import java.util.stream.Collectors

@Service("zhgdMachineryInfoService")
class ZhgdMachineryInfoServiceImpl : ZhgdMachineryInfoService,
    ServiceImpl<ZhgdMachineryInfoMapper, ZhgdMachineryInfo>() {

    private val logger = LoggerFactory.getLogger(ZhgdMachineryInfoServiceImpl::class.java)

    @Autowired
    private var zhgdMachineryAlarmService: ZhgdMachineryAlarmService? = null

    override fun addMachineryInfo(zhgdMachineryInfo: ZhgdMachineryInfo?): BaseResp<Any?> {
        if (zhgdMachineryInfo?.name?.isBlank() == true) {
            return BaseResp.fail("添加失败!名称不能为空")
        }
        val queryWrapper= QueryWrapper<ZhgdMachineryInfo>()
        queryWrapper.eq("name",zhgdMachineryInfo?.name)
        val one = this.getOne(queryWrapper)
        if (one != null) {
            return BaseResp.fail("添加失败,该机具已存在!")
        }
        // 判断下时间是否到期，当前时间>实验结束时间
        if (zhgdMachineryInfo?.testEndTime?.isNotBlank() == true) {

            if (Date().formatString("yyyy-MM-dd").formatDate("yyyy-MM-dd")
                    .compare(zhgdMachineryInfo?.testEndTime?.formatDate("yyyy-MM-dd")!!) > 0
            ) {
                // 添加告警
                try {
                    val zhgdMachineryAlarm = ZhgdMachineryAlarm(
                        type = zhgdMachineryInfo?.type,
                        name = zhgdMachineryInfo?.name, alarmMsg = "该机具:${zhgdMachineryInfo!!.name}实验日期结束,已无法使用"
                    )
                    zhgdMachineryAlarmService?.save(zhgdMachineryAlarm)
                } catch (e: Exception) {
                    if (e is SQLIntegrityConstraintViolationException) {
                        logger.info("该机具:{}的告警信息已存在了!", zhgdMachineryInfo!!.name)
                    } else {
                        logger.error("添加机具告警异常:{}", e.message)
                        e.printStackTrace()
                    }
                }
            }
        }
        if (zhgdMachineryInfo?.testStartTime?.isNotBlank() == true) {
            // 使用中
            zhgdMachineryInfo.status = 1
        }
        if (zhgdMachineryInfo?.testEndTime?.isNotBlank() == true
            && zhgdMachineryInfo?.testPlanEndTime?.isNotBlank() == true
        ) {
            // 实际归还 > 计划归还 状态设为延期归还
            if (zhgdMachineryInfo?.testEndTime?.formatDate("yyyy-MM-dd")
                    ?.compare(zhgdMachineryInfo?.testPlanEndTime?.formatDate("yyyy-MM-dd")!!)!! > 0
            ) {
                zhgdMachineryInfo.status = 3
            } else {
                // 设为归还
                zhgdMachineryInfo.status = 2
            }
        }
        val saveRes = save(zhgdMachineryInfo)
        return if (saveRes) {
            BaseResp.success("添加成功!")
        } else BaseResp.fail("添加失败!")
    }

    override fun getMachineryInfoByName(): List<MachineryInfoByNameDTO?>? {
        val list = this.list(LambdaQueryWrapper())
        val groupInfo = list.stream().collect(Collectors.groupingBy(ZhgdMachineryInfo::name))
        val machineryInfoByNameDTOS: MutableList<MachineryInfoByNameDTO> = mutableListOf()
        val keySet = groupInfo.keys
        for (key in keySet) {
            val machineryInfoByNameDTO = MachineryInfoByNameDTO()
            val zhgdMachineryInfos = groupInfo[key]!!
            var totalAmount = 0
            for (zhgdMachineryInfo in zhgdMachineryInfos) {
                totalAmount += (zhgdMachineryInfo?.amount ?: 0)
            }
            machineryInfoByNameDTO.name = key
            machineryInfoByNameDTO.amount = totalAmount
            machineryInfoByNameDTOS.add(machineryInfoByNameDTO)
        }
        return machineryInfoByNameDTOS
    }

    override fun updateMachineryInfo(zhgdMachineryInfo: ZhgdMachineryInfo?): BaseResp<Any?> {
        // 判断下时间是否到期，当前时间>实验结束时间
        if (zhgdMachineryInfo?.testEndTime?.isNotBlank() == true) {
            if (Date().formatString("yyyy-MM-dd").formatDate("yyyy-MM-dd")
                    .compare(zhgdMachineryInfo?.testEndTime?.formatDate("yyyy-MM-dd")!!) > 0
            ) {
                // 添加告警
                try {
                    val zhgdMachineryAlarm = ZhgdMachineryAlarm(
                        type = zhgdMachineryInfo!!.type,
                        name = zhgdMachineryInfo?.name,
                        alarmMsg = "该机具:${zhgdMachineryInfo!!.name}实验日期结束,已无法使用"
                    )
                    zhgdMachineryAlarmService?.save(zhgdMachineryAlarm)
                } catch (e: java.lang.Exception) {
                    if (e is SQLIntegrityConstraintViolationException) {
                        logger.info("该机具:{}的告警信息已存在了!", zhgdMachineryInfo!!.name)
                    } else {
                        logger.error("添加机具告警异常:{}", e.message)
                        e.printStackTrace()
                    }
                }
            }
        }
        if (zhgdMachineryInfo?.testStartTime?.isNotBlank()==true) {
            // 使用中
            zhgdMachineryInfo?.status = 1
        }
        if (zhgdMachineryInfo?.testEndTime?.isNotBlank() == true
            && zhgdMachineryInfo?.testPlanEndTime?.isNotBlank() == true
        ) {
            // 实际归还 > 计划归还 状态设为延期归还
            if (zhgdMachineryInfo?.testEndTime?.formatDate("yyyy-MM-dd")
                    ?.compare(zhgdMachineryInfo?.testPlanEndTime?.formatDate("yyyy-MM-dd")!!)!! > 0
            ) {
                zhgdMachineryInfo!!.status = 3
            } else {
                // 设为归还
                zhgdMachineryInfo!!.status = 2
            }
        }
        val updateRes = updateById(zhgdMachineryInfo)
        return if (updateRes) {
            BaseResp.success("修改成功!")
        } else BaseResp.fail("修改失败!")
    }

    override fun statisticMachineryInfo(): StatisticMachineryInfoDTO? {
        val allList = this.list(QueryWrapper<ZhgdMachineryInfo>().eq("amount",0))
        val groupInfo = allList.stream().collect(Collectors.groupingBy(ZhgdMachineryInfo::name))
        val keySet = groupInfo.keys
        val statisticMachineryInfoDTO = StatisticMachineryInfoDTO()
        var mainDeviceNum = 0
        var haveArrivedNum = 0
        for (key in keySet) {
            val zhgdMachineryInfos = groupInfo[key]!!
            for (zhgdMachineryInfo in zhgdMachineryInfos) {
                mainDeviceNum += (zhgdMachineryInfo?.amount ?: 0)
            }
            // 获取到货状态的数据
            val haveArrivedNums =
                zhgdMachineryInfos.stream().filter { (_, _, _, status): ZhgdMachineryInfo -> status == 1 }
                    .collect(Collectors.toList())
            for (zhgdMachineryInfo in haveArrivedNums) {
                haveArrivedNum += (zhgdMachineryInfo?.amount ?: 0)
            }
        }
        val arrivedRate = haveArrivedNum.toDouble() / mainDeviceNum
        statisticMachineryInfoDTO.mainDeviceNum = mainDeviceNum
        statisticMachineryInfoDTO.haveArrivedNum = haveArrivedNum
        statisticMachineryInfoDTO.arrivedRate = (arrivedRate * 100).toInt()
        return statisticMachineryInfoDTO
    }

    override fun getMachineryTableInfo(): MachineryTableInfoDTO? {
        val machineryTableInfoDTO = MachineryTableInfoDTO()
        val zhgdMachineryInfos = this.list(QueryWrapper<ZhgdMachineryInfo?>().eq("amount",0))
        var totalDeviceNum = 0
        val usedDeviceNum = zhgdMachineryInfos.stream().filter { (_, _, _, status): ZhgdMachineryInfo -> status == 1 }
            .collect(Collectors.toList()).size
        val delayDeviceNum =
            zhgdMachineryInfos.stream().filter { (_, _, _, status): ZhgdMachineryInfo -> status == 3 || status == 4 }
                .collect(Collectors.toList()).size
        for (zhgdMachineryInfo in zhgdMachineryInfos) {
            totalDeviceNum += (zhgdMachineryInfo?.machineNumber?.toInt() ?: 0)
        }
        machineryTableInfoDTO.totalDeviceNum = totalDeviceNum
        machineryTableInfoDTO.usedDeviceNum= usedDeviceNum
        machineryTableInfoDTO.delayDeviceNum = delayDeviceNum
        machineryTableInfoDTO.machineryInfos = zhgdMachineryInfos
        return machineryTableInfoDTO
    }
}